package com.sz.sidi.oa.katable;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;

import de.kupzog.ktable.KTable;
import de.kupzog.ktable.KTableModel;
import de.kupzog.ktable.SWTX;

/**
 * 
 * @author CYX 将KTable和ShowKTableModel的功能封装起来，使用起来更加方便
 * 
 */
public class ShowKTable extends KTable {
	public final static int L = SWTX.ALIGN_HORIZONTAL_LEFT;
	public final static int R = SWTX.ALIGN_HORIZONTAL_RIGHT;
	public final static int C = SWTX.ALIGN_HORIZONTAL_CENTER;

	// KTable对应的Model
	protected ShowKTableModel model;
	protected List<Object> data = null;// 与Model中的数据一致

	// 这个类里面保存与用户设置一致值，在对应的set方法中处理与Model中的差异
	protected int fixColumnCount = 1;// 默认固定一列,必须 >= 1
	protected int fixRowCount = 1;// 固定行，必须 >=1,表头一定为固定列
	protected int[] columnAligns;
	protected int[] columnWidths;

	// 与Model中的一致
	protected String[] columnTitles;
	protected String[] columnProperties;

	protected int columnCount = 1; // 包括固定列

	/**
	 * 构造函数,一般要使用 FULL_SELECTION 样式,否则那些选中一行的方法无效
	 * 
	 * @param parent
	 * @param style
	 */
	public ShowKTable(Composite parent, int style) {
		super(parent, style);
		fixColumnCount = 1;
		fixRowCount = 1;
		init(null, null);
	}

	/**
	 * 构造函数 请使用 FULL_SELECTION 样式
	 * 
	 * @param parent
	 * @param style
	 * @param columnTitles
	 *            表头
	 * @param columnProperties
	 * 
	 */
	public ShowKTable(Composite parent, int style, String[] columnTitles,
			String[] columnProperties) {
		super(parent, style);
		// 在所有列前面加上默认的序号列，自动计算并设置默认的 columnWidths 和 columnAligns
		fixColumnCount = 1;
		fixRowCount = 1;
		init(columnTitles, columnProperties);
	}

	/*
	 * 带Checkbox的构造函数
	 */
	public ShowKTable(Composite parent, int style, String[] columnTitles,
			String[] columnProperties, String checkBoxProperty) {
		super(parent, style);
		// 在所有列前面加上默认的序号列，自动计算并设置默认的 columnWidths 和 columnAligns
		init(columnTitles, columnProperties, checkBoxProperty);
		fixColumnCount = 2;
		fixRowCount = 1;
	}

	/*
	 * 初始化类
	 */
	private void init(String[] columnTitles, String[] columnProperties) {
		// 初始化对象为可用的类
		setTitlesAndProperties(columnTitles, columnProperties);

	}

	/*
	 * 带Checkbox的初始化
	 */
	private void init(String[] columnTitles, String[] columnProperties,
			String checkboxProperty) {
		setColumnTitles(columnTitles);
		setColumnProperties(columnProperties);
		model = new ShowKTableModel(data, getColumnTitles(),
				getColumnProperties(), getColumnWidths(), getFixRowCount(),
				getFixColumnCount(), "yyyy-MM-dd HH:mm", true, checkboxProperty);
		this.setColumnAligns(this.columnAligns);
		this.setModel(model);
	}

	/**
	 * 设置列信息，包括表头和数据字段
	 * 
	 * @param columnTitles
	 * @param columnProperties
	 */
	public void setTitlesAndProperties(String[] columnTitles,
			String[] columnProperties) {
		setColumnTitles(columnTitles);
		setColumnProperties(columnProperties);
		model = new ShowKTableModel(data, getColumnTitles(),
				getColumnProperties(), getColumnWidths(), getFixRowCount(),
				getFixColumnCount(), "yyyy-MM-dd HH:mm");
		this.setColumnAligns(this.columnAligns);
		this.setModel(model);
	}

	// 默认为1不可设置
	private int getFixRowCount() {
		return this.fixRowCount;
	}

	/**
	 * 设置表头，加上一个序号列
	 * 
	 * @param columnTitles
	 */
	protected void setColumnTitles(String[] columnTitles) {

		// 设置默认固定行固定列
		this.fixColumnCount = 1;
		this.fixRowCount = 1;

		if (columnTitles == null || columnTitles.length == 0) {
			columnAligns = new int[] { C };
			columnWidths = new int[] { 30 };
			// 序号列
			this.columnTitles = new String[] { "" };
			this.columnCount = 1;
			return;
		}

		int length = columnTitles.length;

		this.columnCount = length + 1;

		String[] modelColumnTitles = new String[length + 1];
		modelColumnTitles[0] = "";

		// 根据columnCount来创建默认的 alignment 和 width
		this.columnAligns = new int[this.columnCount];
		this.columnAligns[0] = C;
		this.columnWidths = new int[this.columnCount];
		this.columnWidths[0] = 30;

		for (int index = 0; index < length; index++) {
			modelColumnTitles[index + 1] = columnTitles[index];
			this.columnAligns[index + 1] = L;
			this.columnWidths[index + 1] = 100;
		}
		this.columnTitles = modelColumnTitles;
	}

	/**
	 * 取得表头
	 * 
	 * @return String[]
	 */
	private String[] getColumnTitles() {
		return this.columnTitles;
	}

	/**
	 * 设置表列属性,可设置嵌套属性，形如 fid.fbh
	 * 
	 * @param columnProperties
	 *            String[]
	 */
	protected void setColumnProperties(String[] columnProperties) {

		if (columnProperties == null || columnProperties.length == 0) {
			// 序号列
			this.columnProperties = new String[] { "" };
			return;
		}

		int length = columnProperties.length;
		String[] modelColumnProperties = new String[length + 1];
		modelColumnProperties[0] = "";

		for (int index = 0; index < length; index++) {
			modelColumnProperties[index + 1] = columnProperties[index];
		}
		this.columnProperties = modelColumnProperties;

	}

	/**
	 * 取得属性
	 * 
	 * @return String[] 属性数组
	 */
	private String[] getColumnProperties() {
		return this.columnProperties;
	}

	/**
	 * 设置表格要显示的数据
	 * 
	 * @param data
	 *            List<Object>
	 */
	public void setInput(List data) {
		// 设置 model
		this.data = data;
		if (model != null) {
			model.setData(data);
		}
		redraw();
	}

	/**
	 * 取得表格中显示的数据
	 * 
	 * @return data List<Object>
	 */
	public List getInput() {
		return this.data;
	}

	/**
	 * 刷新表格显示的数据
	 */
	public void refresh() {
		this.redraw();
	}

	/**
	 * 取得选中的行对应的数据列表
	 * 
	 * @return List<Object> 如果没有选中,返回 empty list
	 */
	public List<Object> getSelection() {
		List<Object> selectionObject = new ArrayList<Object>();

		int[] rowArray = this.getRowSelection();

		if (rowArray != null) {
			for (int index = 0; index < rowArray.length; index++) {
				selectionObject.add(model.getRow(rowArray[index]));
			}
		}
		return selectionObject;
	}

	/**
	 * 取和选中的第一行
	 * 
	 * @return Object 选中行对应的对象，如果没有选中，返回 null
	 */
	public Object getFirstSelection() {
		List<Object> list = getSelection();
		if (!list.isEmpty()) {
			return list.get(0);
		}
		return null;
	}

	/**
	 * 设置固定列，
	 * 
	 * @param fixColumnCount
	 *            ,不包括序号列的设置，序号列固定
	 */
	public void setFixColumnCount(int fixColumnCount) {
		if (fixColumnCount < 1) {
			this.fixColumnCount = 1;
		} else {
			this.fixColumnCount = fixColumnCount + 1;
		}
		if (model != null) {
			model.setFixColumnCount(this.fixColumnCount);
		}
	}

	/**
	 * 取得固定列
	 * 
	 * @param int
	 */
	private int getFixColumnCount() {
		return this.fixColumnCount;
	}

	/**
	 * 根据对象的equal方法来选中一行
	 * 
	 * @param Object
	 *            obj
	 * 
	 */
	public void setSelection(Object pobj) {
		// 要验证对象的类型
		if (pobj == null) {
			return;
		}
		int row = 0;
		int rowCount = model.getRowCount();
		while (row < rowCount) {
			Object obj = model.getRow(row);
			if (pobj.equals(obj)) {
				this.setSelection(this.fixColumnCount + 1, row, false);
			}
			row++;
		}

	}

	/**
	 * 根据实体的属性名及对应的值来选中行，如果有多列符合条件， 将选中多列，并返回对象列表
	 * 
	 * @param fieldName
	 *            字段名
	 * @param value
	 *            String, 以字符串形式进行比较
	 * @return List<Object>
	 */
	// public List<Object> setSelection(String fieldName,String value){
	// //TODO
	// return null;
	// }

	/**
	 * 根据实体的属性名及对应的值来选中一行，如果有多列符合条件,选中第一行
	 * 
	 * @param fieldName
	 *            字段名 可以为嵌套字段
	 * @param value
	 *            String, 以字符串形式进行比较
	 */
	public void setFirstSelection(String fieldName, String value) {

		if (fieldName == null || fieldName.trim().equals("") || value == null) {
			return;
		}

		int row = 0;
		int rowCount = model.getRowCount();
		while (row < rowCount) {
			Object obj = model.getRow(row);
			Object fieldValue = getProperty(obj, fieldName);

			if (fieldValue != null
					&& fieldValue.toString().equalsIgnoreCase(value)) {
				this.setSelection(this.fixColumnCount + 1, row, false);
				return;
			}
			row++;
		}
	}

	/**
	 * 
	 * 读取嵌套属性的值
	 * 
	 * @param obj
	 * @param fieldName
	 * @return
	 */
	private Object getProperty(Object obj, String fieldName) {
		if (obj == null || fieldName == null) {
			return null;
		}
		Object tempObj = obj;
		Object value = null;
		String[] fieldList = fieldName.split("\\.");
		for (int index = 0; index < fieldList.length; index++) {
			if (tempObj == null) {
				break;
			}
			value = DoctorConfiguration.getProperty(tempObj, fieldList[index]);
			tempObj = value;

		}
		return value;
	}

	/**
	 * 设置对应的列宽
	 * 
	 * @param pcolumnWidths
	 */
	public void setColumnWidths(int[] pcolumnWidths) {

		if (pcolumnWidths == null || pcolumnWidths.length == 0) {
			// 序号列
			// this.columnWidths = new int[]{30};
			if (model != null) {
				model.setColumnWidths(this.columnWidths);
			}
			return;
		}

		int length = pcolumnWidths.length;

		this.columnWidths = new int[length + 1];
		this.columnWidths[0] = 35;

		for (int index = 0; index < length; index++) {
			this.columnWidths[index + 1] = pcolumnWidths[index];
		}
		// 设置Model的属性
		if (model != null) {
			model.setColumnWidths(this.columnWidths);
		}

	}

	/**
	 * 取得列宽
	 * 
	 * @return int[]
	 * 
	 */
	public int[] getColumnWidths() {
		return this.columnWidths;
	}

	/**
	 * 设置 columnAlignments
	 * 
	 * @param int[] 取本类中的 L(LEFT),C(CENTER),R(RIGHT)
	 */
	public void setColumnAligns(int[] pcolumnAligns) {

		if (pcolumnAligns == null || pcolumnAligns.length == 0) {
			// 序号列
			// this.columnAligns = new int[]{C};
			if (model != null) {
				model.setColumnAligns(this.columnAligns);
			}
			return;
		}

		int length = pcolumnAligns.length;

		this.columnAligns = new int[length + 1];
		this.columnAligns[0] = 30;

		for (int index = 0; index < length; index++) {
			this.columnAligns[index + 1] = pcolumnAligns[index];
		}
		// 设置Model的属性
		if (model != null) {
			model.setColumnAligns(this.columnAligns);
		}

	}

	/**
	 * 取得 Table对应的 ShowKTableModel 用户可以使用Model中的功能，不受ShowKTable的限制
	 * 
	 * @param ShowKTableModel
	 */
	@Override
	public ShowKTableModel getModel() {
		// TODO Auto-generated method stub
		return model;
	}

	/**
	 * 行选中监听器
	 * 
	 * @param KTableRowSelectionListener
	 */
	public void addRowSelectionListener(KTableRowSelectionListener listener) {
		this.addCellSelectionListener(listener);
	}

	/**
	 * 选中行 从 1 开始
	 * 
	 * @param row
	 *            要选中的行号
	 */
	public void selectRow(int row) {
		if (row < 1) {
			return;
		}
		this.setSelection(fixColumnCount + 1, row, false);
	}
	public void setCellStyleProvider(LKCellStyleProvider cellStyleProvider) {
		model.setCellStyleProvider(cellStyleProvider);
	}

	public void setJoinOut(ISKJoinOutValue joinOut) {
		this.getModel().setJoinOut(joinOut);
	}

}
